package com.nfit.shopadmin.service.impl;

import cn.hutool.core.lang.UUID;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.nfit.shopadmin.mapper.AddressMapper;
import com.nfit.shopadmin.mapper.UserMapper;
import com.nfit.shopadmin.service.UserService;
import com.nfit.shopcommon.utils.AESUtil;
import com.nfit.shopcommon.utils.ThreadLocalUtil;
import com.nfit.shopmodel.dto.user.UserInfoDto;
import com.nfit.shopmodel.entity.address.Address;
import com.nfit.shopmodel.entity.user.UserInfo;
import com.nfit.shopmodel.entity.wechat.WechatLoginDto;
import com.nfit.shopmodel.entity.wechat.WechatSession;
import com.nfit.shopmodel.vo.h5.UserInfoVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.util.Date;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import static com.nfit.shopmodel.vo.common.AuthConst.*;

/**
 * ClassName:UserServiceImpl
 * Package:com.nfit.shopadmin.service.impl
 * Description
 *
 * @Author L
 * @Create 2024/12/26 18:36
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Value("${wechat.appid}")
    private String appId; //openid: 用户唯一标识，每个用户对应一个 appid 都会生成一个不同的 openid。

    @Value("${wechat.secret}")
    private String appSecret; // 微信开发者秘钥

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private AddressMapper addressMapper;

    /**
     * 微信一键登录
     * @param code 调用 wx.login 得到的 code
     * @param encryptedData 加密的用户数据
     * @param iv 偏移量
     * @return 返回用户信息
     */
    @Override
    public UserInfo wechatLogin(String code, String encryptedData, String iv) {
        return null;
    }

    /**
     * 手机号码登录
     * @param wechatLoginDto 接收前端专递的数据
     */
    @Transactional
    @Override
    public UserInfo wechatLoginPhone(WechatLoginDto wechatLoginDto) {

        // 1. 获取 openid 和 session_key
        WechatSession wechatSession = this.fetchOpenIdFromWechat(wechatLoginDto.getCode());
        //解密
        JSONObject userJson = this.decryptUserData(  wechatLoginDto.getEncryptedData(),
                                                wechatLoginDto.getIv(),
                                                wechatSession.getSessionKey());

        // 3. 处理解密后的手机号
        String phoneNumber = userJson.getString("phoneNumber"); // 获取手机号
        log.info("解密后的手机号：{}", phoneNumber);
        // 3. 保存或更新用户信息
        return saveOrUpdateUserInfo(wechatSession, userJson);
    }

    /**
     * 根据手机号码查询个人信息
     * @param phone 手机号码
     */
    @Override
    public UserInfoVo getUserInfo(String phone) {
        UserInfo userInfo = userMapper.getUserInfo(phone);
        Address address = addressMapper.findByPhone(phone);
        UserInfoVo userInfoVo = new UserInfoVo();
        //封装vo数据
        userInfoVo.setId(userInfo.getId());
        userInfoVo.setUsername(userInfo.getUsername());
        userInfoVo.setNickName(userInfo.getNickName());
        userInfoVo.setSex(userInfo.getSex());
        userInfoVo.setAvatar(userInfo.getAvatar());
        userInfoVo.setAddress(address.getFullAddress());
        return userInfoVo;
    }

    /**
     * 根据
     * @param userInfoDto 接收前端的数据
     */
    @Transactional
    @Override
    public void update(UserInfoDto userInfoDto) {
        //修改用户信息
        userMapper.update(userInfoDto);
        //修改用户对应的地址表
        addressMapper.update(userInfoDto);
    }

    /**
     * 向微信服务器发送请求，获取 openid
     * @param code 微信登录临时凭证 code
     * @return openid 微信用户唯一标识
     */
    private WechatSession fetchOpenIdFromWechat(String code) {
        String url = String.format(
                "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
                appId, appSecret, code);

        RestTemplate restTemplate = new RestTemplate();
        String response = restTemplate.getForObject(url, String.class);

        JSONObject jsonObject = JSONObject.parseObject(response);
        String openid = jsonObject.getString("openid");
        String sessionKey = jsonObject.getString("session_key"); //会话密钥，用于解密用户数据。
        String errcode = jsonObject.getString("errcode");  //失败状态码
        String errmsg = jsonObject.getString("errmsg"); //失败消息
        //判断
        if (openid == null || (errcode != null && !"0".equals(errcode))) {
            log.error("微信登录失败，errcode: {}, errmsg: {}", errcode, errmsg);
            throw new RuntimeException("微信登录失败：" + (errmsg != null ? errmsg : "未知错误"));
        }
        //封装数据
        WechatSession wechatSession = new WechatSession();
        wechatSession.setOpenid(openid);
        wechatSession.setSessionKey(sessionKey);
        log.info("获取到微信 openid: {}", openid);
        log.info("获取到微信 session_key: {}", sessionKey);
        return wechatSession;
    }

    /**
     * 解密微信用户数据
     * @param encryptedData 加密的用户数据
     * @param iv 偏移量
     * @return 解密后的用户数据 JSON 对象
     */
    private JSONObject decryptUserData(String encryptedData, String iv, String sessionKey) {
        try {
            AESUtil aesUtil = new AESUtil(sessionKey, iv);
            String decryptedData = aesUtil.decrypt(encryptedData);
            log.info("解密后的用户数据：{}", decryptedData);

            return JSONObject.parseObject(decryptedData);
        } catch (Exception e) {
            log.error("用户数据解密失败：{}", e.getMessage());
            throw new RuntimeException("用户数据解密失败：" + e.getMessage(), e);
        }
    }


    /**
     * 保存或更新用户信息
     * @param wechatSession 包含 openId 用户唯一标识
     * @param userJson 解密后的用户数据 JSON 对象
     * @return 保存或更新后的用户信息
     */
    private UserInfo saveOrUpdateUserInfo(WechatSession wechatSession, JSONObject userJson) {
        String phone = userJson.getString("phoneNumber"); //手机号
        //根据openid查询user信息
        UserInfo userInfo = userMapper.selectByOpenid(wechatSession.getOpenid());
        if (userInfo == null) {
            // 如果用户不存在，则注册新用户
            userInfo = new UserInfo();
            //封装地址对象
            Address address = new Address();

            userInfo.setOpenId(wechatSession.getOpenid());
            userInfo.setNickName("shop_"+this.generateRandomString(10));
            userInfo.setAvatar("http://127.0.0.1:9000/shop-bucket/20241211/044cf845560247ecb240cc7de9bb4d2e微信截图_20240408194555.png");
            userInfo.setPhone(phone);
            userInfo.setUsername(phone);
            userInfo.setSex(1);
            userInfo.setAddress(address);
            userInfo.setCreateTime(new Date());
            userInfo.setUpdateTime(new Date());
            userMapper.insert(userInfo);

            address.setPhone(phone); //封装地址表信息
            address.setUserId(userInfo.getId());//封装地址表信息
            addressMapper.save(address);
//            log.info("新用户注册成功：{}", userInfo);
        } else {
            // 如果用户已存在，则更新信息
            userMapper.updateById(userInfo);
//            log.info("用户信息更新成功：{}", userInfo);
        }
        String token = UUID.randomUUID().toString().replaceAll("-","");
        //设置token
        userInfo.setToken(token);
        Long userId = userInfo.getId();
        //把用户id存储redis中
        redisTemplate.opsForValue().set(ADMIN_USER + token,String.valueOf(userId),30,TimeUnit.MINUTES);
        return userInfo;
    }

    /**
     * 随机数字和字母设置名称
     */
    private static String generateRandomString(int length) {
        String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < length; i++) {
            int index = random.nextInt(CHARACTERS.length());
            sb.append(CHARACTERS.charAt(index));
        }
        return sb.toString();
    }
}

